﻿using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Sayook.Framework.Model;
using Sayook.Framework.Tools;
using System;
using System.Threading.Tasks;

namespace Sayook.Framework.AOP.Middleware
{
    /// <summary>
    /// 捕获异常中间件
    /// </summary>
    public class CatchExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IHostEnvironment _env;
        private readonly ILogger<CatchExceptionMiddleware> _logger;

        public CatchExceptionMiddleware(RequestDelegate next, IHostEnvironment env, ILogger<CatchExceptionMiddleware> logger)
        {
            _next = next;
            _env = env;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (Exception e)
            {
                await ExceptionHandler(context, e);
            }
        }

        /// <summary>
        /// 异常处理
        /// </summary>
        /// <param name="context"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        private async Task ExceptionHandler(HttpContext context, Exception ex)
        {
            var exceptionId = Guid.NewGuid().ToString();
            _logger.LogError(ex, "[{exceptionId}]{message}", exceptionId, ex.Message);

            string message;
            if (_env.IsDevelopment())
            {
                message = $"[{exceptionId}]错误消息:{ex.Message}{Environment.NewLine}错误追踪:{ex.StackTrace}";
            }
            else
            {
                message = $"服务出现异常[{exceptionId}]";
            }
            var apiResult = new ApiResult<string>
            {
                Success = false,
                Code = StatusCodes.Status500InternalServerError,
                Message = message
            };
            context.Response.StatusCode = StatusCodes.Status500InternalServerError;
            await context.Response.WriteAsync(apiResult.ToJson());
        }
    }
}